﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cesave.Domain.PermisosModule.Resources;
using Cesave.Domain.PermisosModule.Entities;
using Cesave.Domain.Core;
using System.Data;

namespace Cesave.Domain.PermisosModule.Contracts.Ciclos
{
	/// <summary>
	/// 
	/// </summary>
	public class CicloService
		: ICicloService
	{
		#region Private properties

		/// <summary>
		/// 
		/// </summary>
		private readonly ICicloRepository _cicloRepository;

		#endregion

		#region Constructor

		/// <summary>
		/// 
		/// </summary>
		/// <param name="cicloRepository"></param>
		public CicloService(ICicloRepository cicloRepository)
		{
			if (cicloRepository == null)
				throw new ArgumentNullException(Messages.exception_DependenciesAreNotInitialized);
			_cicloRepository = cicloRepository;
		}

		#endregion

		#region ICicloService Members

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public List<Ciclo> FindAllCiclos()
		{
			return _cicloRepository.FindAllCiclos().ToList();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="status"></param>
		/// <returns></returns>
		public List<Ciclo> FindCiclosByStatus(bool status = true)
		{
			CiclosByStatusSpecification ciclosByStatusSpecification = new CiclosByStatusSpecification(status);
			return _cicloRepository.FindCiclosByStatusSpecification(ciclosByStatusSpecification).ToList();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="cicloGuid"></param>
		/// <returns></returns>
		public Ciclo FindCicloByGuid(Guid cicloGuid)
		{
			if (cicloGuid == Guid.Empty)
				throw new InvalidOperationException(Messages.exception_InvalidArgument);
			CicloByGuidSpecification cicloByGuidSpecification = new CicloByGuidSpecification(cicloGuid);
			return _cicloRepository.FindCicloByGuidSpecification(cicloByGuidSpecification);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="ciclo"></param>
		public void MakeCicloActual(Ciclo ciclo)
		{
			if (ciclo == null)
				throw new ArgumentNullException("ciclo", Messages.exception_InvalidArgument);
			var ciclos = _cicloRepository.GetAll().Where(c => c.CicloGuid != ciclo.CicloGuid).ToList();
			ciclos.ForEach(c =>
			{
				IUnitOfWork thisUnitOfWork = _cicloRepository.StoreContext;
				c.Actual = false;
				_cicloRepository.Modify(c);
				try
				{
					thisUnitOfWork.Commit();
				}
				catch (OptimisticConcurrencyException)
				{
					thisUnitOfWork.RollbackChanges();
					thisUnitOfWork.CommitAndRefreshChanges();
				}
			});
			IUnitOfWork unitOfWork = _cicloRepository.StoreContext;
			ciclo.Actual = true;
			_cicloRepository.Modify(ciclo);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="ciclo"></param>
		public void AddCiclo(Ciclo ciclo)
		{
			if (ciclo == null)
				throw new ArgumentNullException("ciclo", Messages.exception_InvalidArgument);
			IUnitOfWork unitOfWork = _cicloRepository.StoreContext;
			_cicloRepository.Add(ciclo);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="ciclo"></param>
		public void ChangeCiclo(Ciclo ciclo)
		{
			if (ciclo == null)
				throw new ArgumentNullException("ciclo", Messages.exception_InvalidArgument);
			IUnitOfWork unitOfWork = _cicloRepository.StoreContext;
			_cicloRepository.Modify(ciclo);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="ciclo"></param>
		public void DeleteCiclo(Ciclo ciclo)
		{
			if (ciclo == null)
				throw new ArgumentNullException("ciclo", Messages.exception_InvalidArgument);
			IUnitOfWork unitOfWork = _cicloRepository.StoreContext;
			_cicloRepository.Remove(ciclo);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public Ciclo FindCicloActual()
		{
			CicloActualSpecification cicloActualSpecification = new CicloActualSpecification();
			return _cicloRepository.FindCicloByCicloActualSpecification(cicloActualSpecification);
		}

		#endregion

		#region IDisposable Members

		public void Dispose()
		{
			if (_cicloRepository != null &&
				_cicloRepository.StoreContext != null)
				_cicloRepository.StoreContext.Dispose();
		}

		#endregion
	}
}
